<?php

namespace App\Models;

use App\Constants\RedisKey;
use App\Exceptions\GeneralException;
use App\Facades\CommonPlatformRequestFacade;
use App\Facades\RiskPlatformRequestFacade;
use App\Jobs\DealInitSpiderStatusJob;
use App\UserSpiderInfo;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Redis;

/**
 * App\Models\UserAuthSpiderTransLog
 *
 * @property int $id
 * @property int $loan_requests_id 授信ID
 * @property string $riskId 流水ID
 * @property string $type 爬虫类型 1=运营商 2=芝麻信用(淘宝)
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog byLoanRequestIdAndType($params)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog newQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog query()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog whereLoanRequestsId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog whereRiskId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog whereType($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog whereUpdatedAt($value)
 * @mixin \Eloquent
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog byLoanRequestId($params)
 * @property int $loan_request_id 授信申请表ID
 * @property int $user_id 用户id
 * @property string $phone_trade_no 运营商trade编号
 * @property int $phone_status 运营商爬虫状态 1=原始状态 2=成功 3=失败
 * @property string $zhima_trade_no 芝麻信用trade编号
 * @property int $zhima_status 芝麻信用爬虫状态 1=原始状态 2=成功 3=失败
 * @property string $phone_failed_reason 运营商失败原因
 * @property string $zhima_failed_reason 芝麻信用失败原因
 * @property-read \App\Models\UserLoanRequest $loanRequest
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog whereLoanRequestId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog wherePhoneFailedReason($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog wherePhoneStatus($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog wherePhoneTradeNo($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog whereUserId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog whereZhimaFailedReason($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog whereZhimaStatus($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAuthSpiderTransLog whereZhimaTradeNo($value)
 */
class UserAuthSpiderTransLog extends Model
{
    // 爬虫状态 1=初始状态 2=成功 3=失败 4=风控成功 5=爬虫未授权
    const STATUS_INIT = 1, STATUS_SUCCESS = 2, STATUS_FAILED = 3, STATUS_RISK_OK = 4;

    // 爬虫类型
    const TYPE_CARRIER = 1,TYPE_ZHIMA = 2;

    //爬虫类型英文
    const TYPE_CARRIER_ENG = 'carrier',TYPE_ALIPAY_ENG = 'alipay';

    //有效时长
    public static $expireTime = 24*60*60;

    //
    protected $fillable = ['loan_request_id', 'user_id', 'trade_no', 'status', 'failed_reason', 'type'];


    /**
     * model by loan_request_id
     * @param $query
     * @param $params
     * @return mixed
     * @author luwei
     * @date 2019-02-27 19:38
     */
    public function scopeByLoanRequestId($query, $params)
    {
        return $query->where('loan_request_id',$params);
    }

    public function scopeByType($query, $params)
    {
        return $query->where('type',$params);
    }

    public function loanRequest(){
        return $this->belongsTo(UserLoanRequest::class,'loan_request_id','id');
    }

    /**
     * Description: 发送流水号来获取爬虫状态
     * Author: liuju
     * DateTime: 2019-01-29 16:37
     * @param $tradeNo
     * @param $model
     * @param $type
     * @return int
     */
    public static function getStatusByRiskInfo($tradeNo,$model,$type)
    {
        try{
            $carrierKey = sprintf(RedisKey::SPIDER_CARRIER_DATA,$model->user_id);
            $zhimaKey = sprintf(RedisKey::SPIDER_ZHIMA_DATA,$model->user_id);
            if($type == UserAuthSpiderTransLog::TYPE_CARRIER) {
                $data = Redis::get($carrierKey);
                if($data){
                    $data = json_decode($data,true);
                    $cacheTradeNo = $data['trade_no'];
                    if($cacheTradeNo == $tradeNo){
                        return self::STATUS_SUCCESS;
                    }
                }
            }else{
                $data = Redis::get($zhimaKey);
                if($data){
                    $data = json_decode($data,true);
                    $cacheTradeNo = $data['trade_no'];
                    if($cacheTradeNo == $tradeNo){
                        return self::STATUS_SUCCESS;
                    }
                }
            }

            \Log::debug('爬虫请求参数:' . json_encode(['tradeNo' => $tradeNo], JSON_UNESCAPED_UNICODE));
            $res = CommonPlatformRequestFacade::getRiskStatusInfo(['tradeNo' => $tradeNo]);
            \Log::debug('爬虫检查结果:' . json_encode($res, JSON_UNESCAPED_UNICODE));
            $status = self::STATUS_INIT;
            if (!empty($res['code']) && $res['code'] === '01') {
                if ($res['data']['bill']) {
                    $status = self::STATUS_SUCCESS;
                }elseif($res['data']['taskFail']){
                    $status = self::STATUS_FAILED;
                }elseif($res['data']['taskSubmit']){
                    if(($res['data']['task'] === null) || ($res['data']['task'] == true)){
                        $status = self::STATUS_INIT;
                    }else{
                        $status = self::STATUS_FAILED;
                    }
                }

                /*luwei加的 19-03-22*/
                if(($res['data']['taskSubmit']==null)&&($res['data']['task']==null)&&($res['data']['bill']==null)){
                    $status = self::STATUS_FAILED;
                }
                /*luwei加的 19-03-22*/

                //如果爬虫成功 记录缓存
                if($status == self::STATUS_SUCCESS){
                    //通讯详单和芝麻信用加缓存
                    $loan = UserLoanRequest::findOrFail($model->loan_request_id);
                    if($type == UserAuthSpiderTransLog::TYPE_CARRIER){
                        $phoneTaskId = UserPhoneService::select('task_id')->findOrFail($loan->user_phone_service_id);
                        $data = [
                            'trade_no' => $tradeNo,
                            'phone_task_id' => $phoneTaskId->task_id
                        ];
                        Redis::setex($carrierKey,self::$expireTime,json_encode($data,JSON_UNESCAPED_UNICODE));
                    }else{
                        $zhimaTaskId = UserZhiMaInfo::select('task_id')->findOrFail($loan->zhima_id);
                        $data = [
                            'trade_no' => $tradeNo,
                            'zhima_task_id' => $zhimaTaskId->task_id
                        ];
                        Redis::setex($zhimaKey,self::$expireTime,json_encode($data,JSON_UNESCAPED_UNICODE));
                    }
                }
            }else{
                throw new \Exception('风控异常');
            }

            return $status;
        }catch (\Exception $e){
            UserAuthSpiderTransLog::handleByStatus($model->loan_request_id);
            \Log::debug('爬虫状态查询异常:' . $e->getMessage());
        }

    }

    /**
     * Description:处理爬虫信息结果不通过的状态,
     * Author: liuju
     * DateTime: 2019-02-26 09:57
     * @param $loanRequestId
     * @return bool
     * @throws GeneralException
     */
    public static function handleByStatus($loanRequestId)
    {
        $userLoanRequest = UserLoanRequest::find($loanRequestId);
        //授信数据状态必须处于等待风控
        if($userLoanRequest->status != UserLoanRequest::STATUS_WAIT_FOR_RISK){
            return false;
        }
        if (!$userLoanRequest) {
            throw  new  GeneralException('「user_loan_requests数据表中id为（' . $loanRequestId . '）不存在」');
        }

        $userLoanRequest->status = UserLoanRequest::STATUS_RISK_FAILED;
        $userLoanRequest->failed_time = Carbon::now();
        return $userLoanRequest->save();
    }


    /**
     * Description: 根据关联授信数据表id，判断是否允许执行爬虫操作
     * Author: liuju
     * DateTime: 2019-02-26 10:08
     * @param $loanRequestId
     * @param bool $isCache 是否是缓存
     * @return bool
     */
    public static function  canSpider($loanRequestId,$isCache=false)
    {
        $res = false;
        $userLoanRequest = UserLoanRequest::find($loanRequestId);
        if(!$isCache){
            if($userLoanRequest && $userLoanRequest->status == UserLoanRequest::STATUS_WAIT_FOR_RISK) {
                $res = true;
            }
        }else{
            if($userLoanRequest) {
                $res = true;
            }
        }

        return $res;
    }

    /**
     * Description: 根据关联授信数据表id，判断是否允许执行爬虫操作
     * Author: liuju
     * DateTime: 2019-02-26 10:08
     * @param $loanRequestId
     * @return bool
     */
    public static function  canCacheSpider($loanRequestId)
    {
        $res = false;
        $userLoanRequest = UserLoanRequest::find($loanRequestId);
        if($userLoanRequest) {
            $res = true;
        }
        return $res;
    }

    /**
<<<<<<< HEAD
     * @param $data
     * @param $loanRequestId
     * @param $user array 用户id 身份证 手机号 姓名
     * @author luwei
     * @date 2019-03-05 17:34
     */
    public static function pushSpiderData($data, $user, $loanRequestId) {
        try {
            $params = [
                'idNo'    => $user['idNo'],
                'phone'   => $user['phone'],
                'name'    => $user['name'],
                'channel' => '01',
                'data'    => $data
            ];
            $ret    = RiskPlatformRequestFacade::pushSpiderData($params);
            if($ret['code'] == '01'){
                //todo 将流水号入库
                echo '1';
            }
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage());
        }

    }
     /**
     * 收货地址信息
     * @param UserLoanRequest $userLoanRequest
     * @return array
     * @throws \Exception
     * @author luwei
     * @date 2019-03-07 13:51
     */
    public function receiver(UserLoanRequest $userLoanRequest){
        $type = self::TYPE_ALIPAY_ENG;
        $alipay = $this->spiderData($userLoanRequest,$type);
        if(!$alipay){
            return [];
        }
        $receiver = $alipay['alipaydeliveraddresses'];
        $ret = [];
        foreach ($receiver as $value){
            $ret[] = [
                'name' => $value['name'],
                'phone_number' => $value['phone_number'],
                'full_address' => $value['full_address']
            ];
        }
        return $ret;
    }

    /**
     * 通讯详单信息
     * @param UserLoanRequest $userLoanRequest
     * @return array
     * @throws \Exception
     * @author luwei
     * @date 2019-03-07 13:51
     */
    public function phoneDetail(UserLoanRequest $userLoanRequest){
        $type = self::TYPE_CARRIER_ENG;
        $carriers = $this->spiderData($userLoanRequest,$type);
        if(!$carriers){
            return [];
        }
        $calls = array_slice($carriers['calls'],0,3);
        $dial = [];
        $dialed = [];

        $dialData = [];
        $dialedData = [];
        foreach ($calls as $call){
            $billMonth[] = $call['bill_month'];
            foreach ($call['items'] as $item){
                if($item['dial_type'] == 'DIAL'){
//                    $dial[] = $item;
                    if(array_key_exists($item['peer_number'],$dialData)){
                        $dialData[$item['peer_number']]['total'] += 1;
                    }else{
                        $dialData[$item['peer_number']] = [
                            'phone' => $item['peer_number'],
                            'fee' => $item['fee'],
                            'type' => 2,
//                            'time' => Carbon::parse($item['time'])->timestamp,
                            'total' => 1
                        ];
                    }
                }elseif($item['dial_type'] == 'DIALED'){
//                    $dialed[] = $item;
                    if(array_key_exists($item['peer_number'],$dialedData)){
                        $dialedData[$item['peer_number']]['total'] += 1;
                    }else{
                        $dialedData[$item['peer_number']] = [
                            'phone' => $item['peer_number'],
                            'fee' => $item['fee'],
                            'type' => 1,
//                            'time' => Carbon::parse($item['time'])->timestamp,
                            'total' => 1
                        ];
                    }
                }
            }
        }

        $dialData = array_values($dialData);
        $dialedData = array_values($dialedData);

        $dialDataColumn = array_column($dialData,'total');
        $dialedDataColumn = array_column($dialedData,'total');
        array_multisort($dialDataColumn,SORT_DESC,$dialData);
        array_multisort($dialedDataColumn,SORT_DESC,$dialedData);
        $openTime = Carbon::parse($carriers['open_time'])->timestamp;
        $modifyTime = Carbon::parse($carriers['last_modify_time'])->timestamp;
        $ret = [
            'city' => $carriers['city'],
            'open_time' => str_pad($openTime,strlen($openTime)+3,'0'),
            'last_modify_time' => str_pad($modifyTime,strlen($modifyTime)+3,'0'),
            'dial_data' => array_slice($dialData,0,30),
            'dialed_data' => array_slice($dialedData,0,30),
        ];
        return $ret;
    }

    /**
     * 获取爬虫数据并且入库【仅针对于新卡贷APP用户】
     * @param UserLoanRequest $userLoanRequest
     * @param string $type carrier 通话详单 alipay 支付宝信息
     * @return
     * @throws \Exception
     * @author luwei
     * @date 2019-03-07 11:30
     */
    public function spiderData(UserLoanRequest $userLoanRequest, $type = self::TYPE_CARRIER_ENG){
        try{
            $userSpider = UserSpiderInfo::where('type',$type)->where('loan_request_id',$userLoanRequest->id)->first();
            if($userSpider){
                $result = json_decode($userSpider->result,true);
            }else{
                $spider = UserAuthSpiderTransLog::byLoanRequestId($userLoanRequest->id)->byType($type)->first();
                if(!$spider){
                    return [];
                }
                $data = [
                    'tradeNo' => $spider->trade_no
                ];
                $ret = RiskPlatformRequestFacade::spiderInfo($data,$type);
                if($ret['code'] == 01){
                    //todo 入库
                    $result = $ret['data']['resultData'];
                    $params = [
                        'loan_request_id' => $userLoanRequest->id,
                        'user_id' => $userLoanRequest->user_id,
                        'trade_no' => $spider->trade_no,
                        'type' => $type,
                        'result' => json_encode($result,JSON_UNESCAPED_UNICODE)
                    ];
                    UserSpiderInfo::create($params);
                }else{
                    throw new \Exception($ret['message']);
                }
            }
            return $result;

        }catch (\Exception $e){
            throw new \Exception($e->getMessage(),$e->getCode());
        }

    }


}
